package com.gitee.huanminabc.utils_common.dsa.data_structure.ky;

import com.gitee.huanminabc.jcommon.multithreading.SimpleStampedLock;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 * 无冲突哈希表(非线程安全,但是不会发生死循环)
 * 原来的HashMap是链表+红黑树 在并发情况下会可能会导致死循环的情况。
 * 因为在并发调整树节点的时候和调整链表的时候,导致当前节点的下一个节点是自己,导致死循环
 * </p>
 * 经过和ConcurrentHashMap对比发现, ConcurrentHashMap  yyds , 本来想put慢点没关系,查询快就行,但是经过测试查询页必我们的快 5/1
 * </p>
 * 又变为了学习的了, 没法和ConcurrentHashMap比, 也没法和HashMap比, 但是在并发情况下不会发生死循环
 * 如果是并发场景下,建议使用ConcurrentHashMap,非并发场景下使用hashMap
 */
public class HashAcyclicMap<K, V> extends HashMap<K, V> {
    private  Map<K, V>  map ;
    //读写锁
    private final SimpleStampedLock lock = new SimpleStampedLock();

    public HashAcyclicMap() {
        this(16);
    }

    public HashAcyclicMap(int capacity) {
      this.map = new HashMap<>(capacity);
    }




    public V put(K key, V value) {
        return  lock.write(()->map.put(key, value));
    }

    //返回的是旧值
    @Override
    public V remove(Object key) {
       return lock.write(()->map.remove(key));
    }


    @Override
    public V get(Object key) {
        return lock.read(()->map.get(key));
    }



    @Override
    public int size() {
        return lock.read(()->map.size());
    }


    @Override
    public boolean isEmpty() {
        return lock.read(()->map.isEmpty());
    }

    @Override
    public boolean containsKey(Object key) {
        return lock.read(()->map.containsKey(key));
    }


    @Override
    public void clear() {
        lock.write(()->map.clear());
    }

    @Override
    public Set<K> keySet() {
        return lock.read(()->map.keySet());
    }

    @Override
    public Collection<V> values() {
        return lock.read(()->map.values());
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        return lock.read(()->map.entrySet());
    }

    @Override
    public boolean containsValue(Object value) {
        return lock.read(()->map.containsValue(value));
    }

    public V computeIfAbsent(K key,
                             Function<? super K, ? extends V> mappingFunction) {
        return lock.write(()->map.computeIfAbsent(key, mappingFunction));
    }

    public V compute(K key,
                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        return lock.write(()->map.compute(key, remappingFunction));
    }

    @Override
    public V merge(K key, V value,
                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        return lock.write(()->map.merge(key, value, remappingFunction));
    }

    public void putAll(Map<? extends K, ? extends V> m) {
        lock.write(()->map.putAll(m));
    }


}
